#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/dlm_device.h>
#include <linux/uaccess.h>

#include "bxlcdparam_driver.h"
#include <linux/writeback.h>

struct resource *myresource;

static dev_t devid;
static struct cdev raw_cdev;
static struct class *raw_class;
static struct device *raw_device;

char tempbuf[512] = {0};
struct lcdMsg
{
	char key[128];
	char value[128];
} lcdmsg;

/*
接收屏参属性修改处理
*/
static int bxlcdparam_deal(void)
{
	// asmlinkage long fd;

	struct file *filp;
	mm_segment_t old_fs;
	char buf[] = "3333";
	ssize_t bytes_written;

	old_fs = get_fs();
	set_fs(KERNEL_DS);
	filp = filp_open("/root/module/test.txt", O_CREAT|O_RDWR, 0666);
	if (IS_ERR(filp))
	{
		printk( KERN_ALERT"filp_open error\n");
        return -1;
	}

	bytes_written = vfs_write(filp, buf,sizeof(buf),&filp->f_pos);
	if (bytes_written<0)
	{
		printk( KERN_ALERT"vfs_write error\n");
        return -1;
	}

	filp_close(filp,NULL);
	set_fs(old_fs);
	
	

	// printk("bxlcdparam_deal\n");

	// fd = sys_open("/root/module/test.txt", O_CREAT | O_RDWR, 0);

	// {
	// 	/* data */
	// };

	// if (fd < 0)
	// {
	// 	printk("sys_open error\n");
	// 	return -1;
	// }

	// sys_write(fd, "11111", sizeof("11111"));

	// sys_close(fd);

	return 0;
}

static int cdev_open(struct inode *inode, struct file *file)
{
	printk("cdev_open\n");
	return 0;
}
static ssize_t cdev_read(struct file *file, char __user *buf, size_t size, loff_t *loff)
{
	printk("cdev_read\n");
	if (copy_to_user(buf, tempbuf, sizeof(tempbuf)) != 0)
	{
		printk("copy_to_user error\n");
		return -1;
	}

	printk("copy to user ok\n");
	return 0;
}
static ssize_t cdev_write(struct file *file, const char __user *buf, size_t size, loff_t *loff)
{
	printk("cdev_write\n");

	if (copy_from_user(&lcdmsg, buf, size) != 0)
	{
		printk("copy_from_user error\n");
		return -1;
	}
	printk("lcdmsg.key = %s; lcdmsg.value = %s\n", lcdmsg.key, lcdmsg.value);

	bxlcdparam_deal();

	return 0;
}
static int cdev_realease(struct inode *inode, struct file *file)
{
	printk("cdev_realease\n");
	return 0;
}

struct file_operations cdev_bxlcdparam_ops = {
	.owner = THIS_MODULE,
	.open = cdev_open,
	.read = cdev_read,
	.write = cdev_write,
	.release = cdev_realease,
};

static int bxlcdparam_probe(struct platform_device *dev)
{
	int ret;
	struct resource *res;
	printk("bxlcdparam_probe\n");

	res = platform_get_resource(dev, IORESOURCE_IRQ,
								0); // 通过函数拿到device中的资源
	ret = alloc_chrdev_region(&devid, 0, 1, "alloc_chrdev_name");
	if (ret < 0)
	{
		printk("alloc_chrdev_region error\n");
		goto err_chrdev;
	}
	else
	{
		printk("alloc_chrdev_region success\n");
		printk("major=%d\n,minor = %d", MAJOR(devid), MINOR(devid));

		raw_cdev.owner = THIS_MODULE;
		cdev_init(&raw_cdev, &cdev_bxlcdparam_ops);
		cdev_add(&raw_cdev, devid, 1);
		if (ret < 0)
		{
			goto err_cdevadd;
		}

		raw_class = class_create(THIS_MODULE, "bxlcdparam");
		if (IS_ERR(raw_class))
		{
			ret = PTR_ERR(raw_device);
			goto err_class_create;
		}

		raw_device = device_create(raw_class, NULL, devid, NULL, "bxlcdparam");
		if (IS_ERR(raw_device))
		{
			ret = PTR_ERR(raw_device);
			goto err_device_create;
		}
		printk("bxlcdparam probe ok\n");
	}
	return 0;

err_device_create:
	class_destroy(raw_class);

err_class_create:
	cdev_del(&raw_cdev);

err_cdevadd:
	unregister_chrdev_region(devid, 1);

err_chrdev:
	return ret;
}

static int bxlcdparam_remove(struct platform_device *dev)
{
	printk("bxlcdparm_remove\n");
	return 0;
}

const struct platform_device_id bxlcdparam_id_table = {
	.name = "bxlcdparam",
};

struct platform_driver bxdriver = {
	.probe = bxlcdparam_probe,
	.remove = bxlcdparam_remove,
	.driver = {
		.name = "bxlcdparam",
		.owner = THIS_MODULE,
	},
	.id_table = &bxlcdparam_id_table,
};

static int lcdparam_driver_init(void)
{
	printk("bxlcdparem init\n");
	platform_driver_register(&bxdriver);
	return 0;
}

static void lcdparam_driver_exit(void)
{
	cdev_del(&raw_cdev);
	unregister_chrdev_region(devid, 1);

	device_destroy(raw_class, devid);
	class_destroy(raw_class);

	platform_driver_unregister(&bxdriver);
	printk("bxlcdparam_exit\n");
}

module_init(lcdparam_driver_init);
module_exit(lcdparam_driver_exit);

MODULE_AUTHOR("BX");
MODULE_LICENSE("GPL");
MODULE_VERSION("V1.0");